<?php

namespace App\Http\Controllers\AgentAdmin;

use App\Enums\AvailableStatus;
use App\Enums\LotteryAwardType;
use App\Http\Controllers\Controller;
use App\Models\AgentUser;
use App\Models\Lottery;
use App\Models\LotteryAward;
use App\Models\LotteryRecord;
use App\Models\LotteryUser;
use App\Services\ObsService;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Vinlon\Laravel\LayAdmin\Exceptions\AdminException;

class LotteryController extends Controller
{
    /** @var ObsService */
    private $obsService;

    public function __construct(ObsService $obsService)
    {
        $this->obsService = $obsService;
    }

    /** 查询抽奖活动列表 */
    public function index()
    {
        /** @var AgentUser $user */
        $user = auth()->user();

        $query = Lottery::query()
            ->where('agent_id', $user->agent_id)
            ->when(request()->keyword, function ($q) {
                $likeVal = '%' . request()->keyword . '%';

                return $q->where('name', 'like', $likeVal);
            })
            ->orderByDesc('id');

        return paginate_result($query);
    }

    /** 查询活动信息 */
    public function show($lotteryId)
    {
        $lottery = $this->getAgentLottery($lotteryId);
        if (!$lottery) {
            return [];
        }
        $lottery->load('awards');

        return $lottery;
    }

    /** 创建抽奖活动 */
    public function store()
    {
        request()->validate([
            'name' => 'required',
            'start_time' => 'required',
            'end_time' => 'required',
            'description' => 'required',
            'awards' => 'required | array',
        ]);
        /* @var Lottery $lottery */
        if (request()->id) {
            $lottery = $this->getAgentLottery(request()->id);
            if ($lottery->status->is(AvailableStatus::ENABLED)) {
                throw new AdminException('开启中的活动不可编辑');
            }
        } else {
            /** @var AgentUser $agentUser */
            $agentUser = auth()->user();
            $lottery = new Lottery();
            $lottery->agent_id = $agentUser->agent_id;
        }
        $lottery->name = request()->name;
        $lottery->start_time = request()->start_time;
        $lottery->end_time = request()->end_time;
        $lottery->description = request()->description;

        $startTime = Carbon::parse(request()->start_time);
        $endTime = Carbon::parse(request()->end_time);
        if ($startTime->gte($endTime)) {
            throw new AdminException('开始时间必须小于结束时间');
        }
        $awards = request()->awards;
        $sumRatePerLevel = [];
        foreach ($awards as $award) {
            \Validator::validate($award, [
                'name' => 'required',
                'amount' => 'required',
                'level' => 'required',
                'rate' => 'required',
                'user_limit' => 'required',
                'logo_url' => 'required',
                'description' => 'required',
            ]);
            $level = Arr::get($award, 'level');
            $sumRatePerLevel = Arr::add($sumRatePerLevel, $level, 0);
            $sumRatePerLevel[$level] += Arr::get($award, 'rate');
        }
        if (count($awards) > 6) {
            throw new AdminException('奖品数量不能超过6个');
        }
        foreach ($sumRatePerLevel as $level => $sumRate) {
            if ($sumRate > 100) {
                throw new AdminException('同一等级的奖品中奖率之和不能超过100%');
            }
        }
        \DB::transaction(function () use ($lottery, $awards) {
            $lottery->save();
            $awardIds = [];
            foreach ($awards as $award) {
                $awardObj = LotteryAward::query()->find($award['id']);
                if (!$awardObj) {
                    $awardObj = new LotteryAward();
                    $awardObj->lottery_id = $lottery->id;
                    $awardObj->type = LotteryAwardType::ENTITY;
                    $awardObj->refer_id = 0;
                }
                $awardObj->fill($award);
                $awardObj->save();
                $awardIds[] = $awardObj->id;
            }
            // 删除奖品
            $lottery->awards()->whereNotIn('id', $awardIds)->delete();
        });
    }

    /** 开启活动 */
    public function open($id)
    {
        $lottery = $this->getAgentLottery($id);
        //同一时间段内只能有一个活动开启
        $hasConflict = Lottery::query()
            ->where('agent_id', $lottery->agent_id)
            ->where('id', '!=', $lottery->id)
            ->where('status', AvailableStatus::ENABLED)->count();
        if ($hasConflict) {
            throw new AdminException('同一时间只能开启一个活动');
        }
        $lottery->status = AvailableStatus::ENABLED;
        $lottery->save();
    }

    /** 关闭活动 */
    public function close($id)
    {
        $lottery = $this->getAgentLottery($id);
        $lottery->status = AvailableStatus::DISABLED;
        $lottery->save();
    }

    /** 删除抽奖活动 */
    public function destroy($id)
    {
        $lottery = $this->getAgentLottery($id);
        if ($lottery->status->is(AvailableStatus::ENABLED)) {
            throw new AdminException('已开启的活动不可删除');
        }
        $recordsCount = LotteryRecord::query()->where('lottery_id', $id)->count();
        if ($recordsCount > 0) {
            throw new AdminException('有人参与过的活动不能删除');
        }
        //删除抽奖活动以及对应的奖项, 参与用户
        $lottery->awards()->delete();
        $lottery->delete();
        LotteryUser::query()->where('lottery_id', $id)->delete();
    }

    /** 查询奖品列表 */
    public function listAwards($lotteryId)
    {
        return LotteryAward::query()->where('lottery_id', $lotteryId)
            ->orderByDesc('level')
            ->orderBy('amount')
            ->get();
    }

    /** 上传奖品图片 */
    public function uploadAwardImage()
    {
        request()->validate([
            'file' => ['image', 'mimes:jpg,jpeg,png,gif', 'max:20480'],
        ], [
            'file.max' => '图片尺寸不能超过2M',
            'file.mimes' => '图片格式必须为jpg/jpeg/png/gif',
        ]);
        $key = 'lottery_award/' . uniqid();
        $file = request()->file('file');
        $imageUrl = $this->obsService->upload($key, $file);

        return [
            'image_url' => $imageUrl,
        ];
    }

    private function getAgentLottery($lotteryId)
    {
        /** @var AgentUser $agentUser */
        $agentUser = auth()->user();

        return Lottery::query()->where('agent_id', $agentUser->agent_id)
            ->find($lotteryId);
    }
}
